package gri_global_config;

use xml_helper;
use Data::Dumper;

my $error="";

sub new {
my $self={};
shift;
my $f=shift;

	$self->{xml_helper}=new xml_helper();

	my $d=""; my $fd;
	if(!open($fd,$f)) {
		$error="Can not open file '$f' : $!";
		return(undef);
	}
	$d=join("",<$fd>);
	close($fd);
	my $x=$self->{xml_helper}->parse($d);
	if(! $x) {
		$error="Unable to parse XML!";
		return undef;
	}

	# Check the data is in the format we expect.

	my ($data,$attrs,$elements)=$self->{xml_helper}->get_element("");
	if(!defined($data)) {
		$error="Invalid data to parse [top level]";
		return(undef);
	}
	if(scalar(@$elements)!=1) {
		$error="More than 1 top level element!";
		return(undef);
	}
	if($elements->[0] ne "gri_global_config") {
		$error="Top level element is not 'gri_global_config'";
	}
	($data,$attrs,$elements)=$self->{xml_helper}->get_element("gri_global_config#0");
	if(!defined($data)) {
		$error="Invalid data to parse [gri_global_config#0]";
		return(undef);
	}
	#################################################################
	# We expect the ports, variables and directories entries.	#
	#################################################################
	$self->{variables}={};
	$self->{ports}={};
	$self->{directories}={};
	my @D=("directories","variables","ports");
	for my $el (@D) {
		if(! grep {$_ eq "gri_global_config#0|$el#0"} @$elements) {
			$error="Missing '$el' element.";
			return(undef);
		}
	}
	for my $cent (@$elements) {
		if(! grep {$_ eq $cent} (
			"gri_global_config#0|directories#0",
			"gri_global_config#0|variables#0",
			"gri_global_config#0|group_handling#0",
			"gri_global_config#0|email_addresses#0",
			"gri_global_config#0|tmp_content#0",
			"gri_global_config#0|ports#0")) {
			$error="Unexpected element '$cent' found.";
			return(undef);
		}
	}
	#################################################################
	# Get the port information and error if not available.		#
	#################################################################
	my ($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|ports#0|authd#0");
	if(!defined($data2)) {
		$error="Missing 'authd' port definition.";
		return(undef);
	}
	$data2=~s/^\s+//;
	if(!length($data2)) {
		$error="Missing 'authd' port value.";
		return(undef);
	}
	if(!exists($attrs2->{host})) {
		$error="Authd element does not contain 'host' attribute.";
		return(undef);
	}
	$self->{ports}->{authd_host}=$attrs2->{host};
	$self->{ports}->{authd}=int($data2);
	$self->{ports}->{authd_protocol}=0; # insecure
	if(exists($attrs2->{protocol})) {
		my $p=lc($attrs2->{protocol});
		if($p ne 'secure' && $p ne 'insecure') {
			$error="Protocol setting of '$p' is not supported (try 'secure' or 'insecure').";
			return(undef);
		}
		$p=0 if $p eq 'insecure';
		$p=1 if $p eq 'secure';
		$self->{ports}->{authd_protocol}=$p;
	}
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|ports#0|backend#0");
	if(!defined($data2)) {
		$error="Missing 'backend' port definition.";
		return(undef);
	}
	$data2=~s/^\s+//;
	if(!length($data2)) {
		$error="Missing 'backend' port value.";
		return(undef);
	}
	$self->{ports}->{backend_protocol}=0; # insecure
	$self->{ports}->{backend}=int($data2);
	if(exists($attrs2->{protocol})) {
		my $p=lc($attrs2->{protocol});
		if($p ne 'secure' && $p ne 'insecure') {
			$error="Protocol setting of '$p' is not supported (try 'secure' or 'insecure').";
			return(undef);
		}
		$p=0 if $p eq 'insecure';
		$p=1 if $p eq 'secure';
		$self->{ports}->{backend_protocol}=$p;
	}
	#################################################################
	# Get all the variable elements...				#
	#################################################################
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|variables#0");
	for my $c (@$elements2) {
		if($c !~ /.*variable#\d+$/) {
			$error="Unexpected element found '$c'";
			return(undef);
		}
		my ($data3,$attrs3,$elements3)=$self->{xml_helper}->get_element($c);
		if(!exists($attrs3->{name})) {
			$error="Element '$c' missing attribute 'name'.";
			return(undef);
		}
		if(!exists($attrs3->{value})) {
			$error="Element '$c' missing attribute 'value'.";
			return(undef);
		}
		$self->{variables}->{$attrs3->{name}}=$attrs3->{value};
	}
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|tmp_content#0");
	if(!defined($data2)) {
		$error="Missing mandatory section gri_global_config#0|tmp_content#";
		return(undef);
	}
	if(! exists($attrs2->{localdir}) || !exists($attrs2->{urlref})) {
		$error="Missing mandatory attribute in tmp_contents!";
		return(undef);
	}
	$self->{tmp_content_localdir}=$attrs2->{localdir};
	$self->{tmp_content_urlref}=$attrs2->{urlref};

	#################################################################
	# Make sure all the directories are defined.			#
	#################################################################
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|directories#0");
	@D=("portals","templates","auditdir","reports","meta_reports","alerts","users","database","docrepos","requests");
	for my $el (@D) {
		if(! grep {$_ eq "gri_global_config#0|directories#0|$el#0"} @$elements2) {
			$error="Missing '$el' element.";
			return(undef);
		}
	}
	#################################################################
	# Make sure we only have recognised directories.		#
	#################################################################
	for my $cent (@$elements2) {
		if(! grep {$_ eq $cent} (
			"gri_global_config#0|directories#0|auditdir#0",
			"gri_global_config#0|directories#0|portals#0",
			"gri_global_config#0|directories#0|templates#0",
			"gri_global_config#0|directories#0|macros#0",
			"gri_global_config#0|directories#0|alerts#0",
			"gri_global_config#0|directories#0|users#0",
			"gri_global_config#0|directories#0|database#0",
			"gri_global_config#0|directories#0|docrepos#0",
			"gri_global_config#0|directories#0|requests#0",
			"gri_global_config#0|directories#0|meta_reports#0",
			"gri_global_config#0|directories#0|reports#0")) {
			$error="Unexpected element '$cent' found.";
			return(undef);
		}
	}
	for my $el (@D) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|directories#0|$el#0");
		$data2=~s/^\s+//;
		$data2=~s/\s+$//;
		if(!length($data2)) {
			$error="No value given for directory '$el'.";
		}
		$self->{directories}->{$el}=$data2;
	}

	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|group_handling#0");
	if(!defined($elements2) || ! @$elements2) {
		$self->{gr_supported}=0;		
	} else {
	
		@D=("supported","gr_query_port","gr_query_hosts");
		for my $el (@D) {
			if(! grep {$_ eq "gri_global_config#0|group_handling#0|$el#0"} @$elements2) {
				$error="Missing '$el' element.";
				return(undef);
			}
			my ($data3,$attrs3,$elements3)=$self->{xml_helper}->get_element("gri_global_config#0|group_handling#0|$el#0");
			if($el eq 'supported') {
				$self->{gr_supported}=int($data3);
				last if int($data3)==0;
			} else {
				$self->{$el}=$data3;
			}
		}
	}
	#################################################################
	# Make sure all the email_addresses are defined.		#
	#################################################################
	($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|email_addresses#0");
	@D=("access_requests");
	for my $el (@D) {
		if(! grep {$_ eq "gri_global_config#0|email_addresses#0|$el#0"} @$elements2) {
			$error="Missing '$el' element.";
			return(undef);
		}
	}
	#################################################################
	# Make sure we only have recognised directories.		#
	#################################################################
	for my $cent (@$elements2) {
		if(! grep {$_ eq $cent} (
			"gri_global_config#0|email_addresses#0|access_requests#0",
			"gri_global_config#0|email_addresses#0|email_transport_cmd#0",
			"gri_global_config#0|email_addresses#0|email_transport_args#0",
			"gri_global_config#0|email_addresses#0|email_sent_from#0",
			)) {
			$error="Unexpected element '$cent' found.";
			return(undef);
		}
	}
	for my $el (@D) {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|email_addresses#0|$el#0");
		$data2=~s/^\s+//;
		$data2=~s/\s+$//;
		if(!length($data2)) {
			$error="No value given for email address '$el'.";
		}
		$self->{email_addresses}->{$el}=$data2;
	}
	# Optional entries now...
	for my $el ('email_transport_cmd','email_transport_args','email_sent_from') {
		($data2,$attrs2,$elements2)=$self->{xml_helper}->get_element("gri_global_config#0|email_addresses#0|$el#0");
		next if !defined($data2);
		$data2=~s/^\s+//;
		$data2=~s/\s+$//;
		$self->{email_addresses}->{$el}=$data2;
	}

	bless($self);
	return $self;
}

sub get_port($$) {
my $self=shift;
my $port=shift;

	if(!exists($self->{ports}->{$port})) {
		$error="Details of port '$port' not available.";
		return undef;
	}
	return $self->{ports}->{$port};
}

sub get_variable {
my $self=shift;
my $var=shift;

	if(!exists($self->{variables}->{$var})) {
		$error="Details of variable '$var' not available.";
		return undef;
	}
	return $self->{variables}->{$var};
}

sub get_variable_list {
my $self=shift;

	return keys(%{$self->{variables}});
}

sub get_directory {
my $self=shift;
my $dir=shift;

	if(!exists($self->{directories}->{$dir})) {
		$error="Details of variable '$dir' not available.";
		return undef;
	}
	return $self->{directories}->{$dir};
}

# Read in the details of the following section and work out the email
# command to use.

#	<email_addresses>
#        <email_transport_cmd>sendmail</email_transport_cmd> <!-- could be mailx too !-->
#		<email_transport_args>-f simon@romero-edwards.name</email_transport_args>
#		<email_sent_from>An-address-name</email_sent_from>
#		<access_requests>simon.edwards@advantsys.co.uk</access_requests>
#	</email_addresses>

sub generate_email_command {
my $self=shift;
my $default_cmd="/usr/sbin/sendmail";
my $default_args="-v -t";

	my $x=$self->{email_addresses}->{email_transport_cmd};
	if(exists($self->{email_addresses}->{email_transport_cmd})) {
		if(substr($x,0,1) eq '/') {
			$default_cmd=$x;
		} else {
			# No path component, so attempt to work one out based on standard
			# likely paths.
			for my $cp ('/usr','/usr/sbin','/usr/local/bin','/sbin','/bin','/usr/bin') {
				if(-x "$cp/$x") {
					$default_cmd="$cp/$x";
					last;
				}
			}
		}
	}

	# Ok, see if any args need to be added.

	if(exists($self->{email_addresses}->{email_transport_args})) {
		$default_args=$self->{email_addresses}->{email_transport_args};
	}

	# sendmail sanity check - ensure -t is provided if running sendmail.

	if($default_cmd =~ /sendmail/ && $default_args !~ /\-t/) {
		$default_args.=' -t';
	}
	return "$default_cmd $default_args";
}

sub get_email_sent_from_address {
my $self=shift;
my $default="Reporting-Intranet";

	if(exists($self->{email_addresses}->{email_sent_from})) {
		return $self->{email_addresses}->{email_sent_from};
	}
	return $default;
}

sub get_email_address {
my $self=shift;
my $email=shift;

	if(!exists($self->{email_addresses}->{$email})) {
		$error="Details of email address '$email' not available.";
		return undef;
	}
	return $self->{email_addresses}->{$email};
}

sub error {
	return $error;
}

sub get_localdir {
my $self=shift;

	return $self->{tmp_content_localdir};
}

sub get_urlref {
my $self=shift;

	return $self->{tmp_content_urlref};
}

sub get_gr_supported {
my $self=shift;

	if(! $self->{gr_supported}) {
		return {
			gr_supported => 0,
			gr_query_hosts => [],
			gr_query_port => 9999,
		};
	}
	return {
		gr_supported => $self->{gr_supported},
		gr_query_hosts => $self->{gr_query_hosts},
		gr_query_port => $self->{gr_query_port},
	};
}
1;

